package se.sll.itintegration.catalogue.camel.processor;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.camel.Body;
import org.apache.camel.Exchange;
import org.apache.camel.Property;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

import se.sll.itintegration.catalogue.gui.data.ProductView;
import se.sll.service.catalogue.common.rest.model.CodeSystem;
import se.sll.service.catalogue.common.rest.model.CodeSystemCode;
import se.sll.service.catalogue.common.rest.model.Product;

/**
 *
 * @author khaleddaham
 */
public class ProductProcessor {

    private static final ProductProcessor INSTANCE = new ProductProcessor();

    private final ObjectMapper mapper = new ObjectMapper();

    private ProductProcessor() {
    }

    /**
     *
     * @param exchange
     */
    public void createView(Exchange exchange) {
        exchange.setProperty("view", new ProductView());
    }

    /**
     *
     * @param exchange
     * @param grouped
     * @param view
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    public void mergeToProductView(Exchange exchange, @Body List<Exchange> grouped, @Property("view") ProductView view) throws IOException, JsonMappingException, IOException {
        @SuppressWarnings("unchecked")
        List<Product> productList = grouped.get(0).getIn().getBody(List.class);
        @SuppressWarnings("unchecked")
        Map<String, CodeSystem> codeSystemList = grouped.get(1).getIn().getBody(Map.class);
        view.setProduct(productList);
        if (codeSystemList != null) {
            view.setCodeSystem(codeSystemList);
        }
        exchange.getIn().setBody(view);
    }

    /**
     *
     * @param exchange
     * @return
     * @throws IOException
     */
    private Map<String, Product> convertJsonToProductMap(Exchange exchange) throws IOException {
        mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        List<se.sll.service.catalogue.common.rest.model.Product> responses
                = mapper.readValue(exchange.getIn().getBody(String.class), new TypeReference<List<se.sll.service.catalogue.common.rest.model.Product>>() {
                });
        Map<String, Product> map = new HashMap<>();
        for (Product p : responses) {
            map.put(p.getName(), p);
        }
        return map;
    }

    private List<se.sll.service.catalogue.common.rest.model.Product> convertJsonToProductList(Exchange exchange) throws IOException {
        return mapper.readValue(exchange.getIn().getBody(String.class), new TypeReference<List<se.sll.service.catalogue.common.rest.model.Product>>() {
        });
    }

    /**
     *
     * @param exchange
     * @return
     * @throws IOException
     */
    private Map<String, CodeSystem> convertJsonToCodeSystem(Exchange exchange) throws IOException {
        List<CodeSystem> responses
                = mapper.readValue(exchange.getIn().getBody(String.class), new TypeReference<List<CodeSystem>>() {
                });
        Map<String, CodeSystem> map = new HashMap<>();
        for (CodeSystem p : responses) {
            map.put(p.getOid(), p);
        }
        return map;
    }

    /**
     *
     * @param exchange
     * @return
     * @throws IOException
     */
    private Map<String, CodeSystemCode> convertJsonToCode(Exchange exchange) throws IOException {
        List<CodeSystemCode> responses
                = mapper.readValue(exchange.getIn().getBody(String.class), new TypeReference<List<CodeSystemCode>>() {
                });
        Map<String, CodeSystemCode> map = new HashMap<>();
        for (CodeSystemCode p : responses) {
            map.put(p.getCode(), p);
        }
        return map;
    }

    /**
     *
     * @param exchange
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    public void productResponseJSON(Exchange exchange) throws JsonParseException, JsonMappingException, IOException {
        exchange.getIn().setBody(convertJsonToProductMap(exchange));
    }

    public void translateToProtuctList(Exchange exchange) throws IOException {
        exchange.getIn().setBody(convertJsonToProductList(exchange));
    }

    public void translateToCodeMap(Exchange exchange) throws IOException {
        exchange.getIn().setBody(convertJsonToCode(exchange));
    }

    public void translateToCodeSystemMap(Exchange exchange) throws IOException {
        exchange.getIn().setBody(convertJsonToCodeSystem(exchange));
    }

    public static final ProductProcessor getInstance() {
        return INSTANCE;
    }
}
